package breadbox.client.operations;

import java.io.IOException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

import breadbox.client.files.Chunk;
import breadbox.client.files.Chunker;
import breadbox.client.files.FileInput;
import breadbox.client.logging.Logger;
import breadbox.dataManagement.RMIMessage;
import breadbox.pastry.Message;

/**
 * Code necessary for executing a Put operation
 * @author Forrest
 *
 */
public class Put extends Operation {
	private Chunker c;
	private RMIMessage rmiServer;
	private boolean compression;
	
	/**
	 * Construct a new Put Operation
	 * @param f String filename to execute PUT
	 * @param server RMIMessage server to send file
	 */
	public Put(String f, RMIMessage server) {
		this(f, server, -1, false, false, false, false);
	}
	
	/**
	 * Construct a new Put Operation by setting a specific chunksize
	 * @param f String filename to execute PUT
	 * @param server RMIMessage server to send file
	 * @param chunksize int chunksize for chunker
	 */
	public Put(String f, RMIMessage server, int chunksize, 
			boolean encrypt, boolean compress, boolean hashcheck, boolean publicfile) {
		FileInput fs = new FileInput(f, compress);
		c = new Chunker(fs, chunksize, encrypt, hashcheck, publicfile);
		rmiServer = server;
		this.compression = compress;
	}
	
	/**
	 * Send a message for each chunk
	 * @return messages List<Message>
	 */
	public List<Message> send() {
		// get the chunks for the current file
		Logger l = new Logger();
		ArrayList<Message> messages = new ArrayList<Message>();
		List<Chunk> chunks = c.getChunks();

		// don't allow puts of empty files
		if (chunks == null) {
			System.err.println("Chunk error: Empty file");
			return null;
		}
		
		// send a message with each chunk
		for (Chunk k: chunks) {
			Message m = sendMessage(k);
			if (m == null) {
				return null;
			}
			messages.add(m);
		}
		
		// close the file and write the log
		c.getFileStream().close();
		try {
			l.writeChunks(chunks, compression);
		} catch (IOException e) {
			System.err.println("Put error: Unable to write log file");
			return null;
		}
		return messages;
	}

	/**
	 * Send the message
	 * @param k
	 * @return Message (for debugging purposes)
	 * @throws IOException 
	 */
	protected Message sendMessage(Chunk k) {
		// serialize the chunk
		byte[] b = null;
		try {
			b = k.toByteArray();
		} catch (IOException e) {
			System.err.println("Put error: Unable to serialize chunk");
			return null;
		}
		
		// send the message to the server
		Message m = new Message(k.getID(), OperationType.PUT.toString(), b);
		try {
            rmiServer.sendMessage(m);
        } catch(RemoteException e) {
            System.err.println("Put error: Unable to send message");
            return null;
        }

		return m;
	}
}
